{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "SVM的原理：  \n",
    "https://windmising.gitbook.io/liu-yu-bo-play-with-machine-learning/di-shi-yi-zhang-zhi-cheng-xiang-liang-ji-svm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from SimpleSMO import SimpleSMO\n",
    "from PlattSMO import PlattSMO\n",
    "import utils\n",
    "import kernel"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 简化版SMO算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1., -1.,  1., -1.,  1.,  1.,  1., -1., -1., -1.])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataArr, labelArr = utils.loadDataSet('testSet.txt')\n",
    "labelArr[:10]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "array([-1., -1.,  1., -1.,  1.,  1.,  1., -1., -1., -1.])  \n",
    "\n",
    "labelArr分为两类，分别是1和-1。  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Wall time: 1.99 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "simple = SimpleSMO(C = 0.6, toler = 0.001, maxIter = 40)\n",
    "b,alphas = simple.train(dataArr, labelArr)\n",
    "w = simple.get_w(alphas, dataArr, labelArr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w =  [ 0.81425078 -0.27173749]\n",
      "b =  -3.8372842889994776\n",
      "alphas =  [[1.81241093e-02 3.42760235e-01 2.08166817e-17 1.39537210e-01\n",
      "  2.21347134e-01]]\n",
      "support vectors = \n",
      "[4.658191 3.507396] -1.0\n",
      "[ 3.457096 -0.082216] -1.0\n",
      "[ 5.286862 -2.358286] 1.0\n",
      "[6.080573 0.418886] 1.0\n"
     ]
    }
   ],
   "source": [
    "print (\"w = \", w)\n",
    "print (\"b = \", b)\n",
    "print (\"alphas = \", alphas[alphas>0])\n",
    "print (\"support vectors = \")\n",
    "# 打印支撑向量\n",
    "for i in range(100):\n",
    "    if alphas[i]>1e-3: print( dataArr[i],labelArr[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "w =  [ 0.81425078 -0.27173749]  \n",
    "b =  -3.8372842889994776  \n",
    "alphas =  [[1.81241093e-02 3.42760235e-01 2.08166817e-17 1.39537210e-01\n",
    "  2.21347134e-01]]  \n",
    "support vectors =   \n",
    "[4.658191 3.507396] -1.0  \n",
    "[ 3.457096 -0.082216] -1.0  \n",
    "[ 5.286862 -2.358286] 1.0  \n",
    "[6.080573 0.418886] 1.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "utils.showSMO(dataArr, labelArr, alphas, w, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Platt加速的SMO算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataArr,labelArr = utils.loadDataSet('testSet.txt')\n",
    "platt = PlattSMO(0.6, 0.001, 40)\n",
    "oS = platt.train(dataArr, labelArr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "\n",
    "如果开启verbose，还可以看到以下内容  \n",
    "iter: 1 i:99, pairs changed 4  \n",
    "iter: 2 i:46, pairs changed 0  \n",
    "iter: 3 i:99, pairs changed 5  \n",
    "iter: 4 i:97, pairs changed 2  \n",
    "iter: 5 i:97, pairs changed 1  \n",
    "iter: 6 i:97, pairs changed 1  \n",
    "iter: 7 i:97, pairs changed 4  \n",
    "iter: 8 i:97, pairs changed 1  \n",
    "iter: 9 i:97, pairs changed 2  \n",
    "iter: 10 i:97, pairs changed 2  \n",
    "iter: 11 i:97, pairs changed 1  \n",
    "iter: 12 i:97, pairs changed 2  \n",
    "iter: 13 i:97, pairs changed 0  \n",
    "iter: 14 i:99, pairs changed 3  \n",
    "iter: 15 i:97, pairs changed 0  \n",
    "iter: 16 i:99, pairs changed 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w =  [ 0.62172526 -0.2926272 ]\n",
      "b =  -2.8697555652712596\n",
      "alphas =  [[0.13853542 0.0019828  0.00530804 0.05671226 0.00327745 0.04086031\n",
      "  0.04639355 0.07897462 0.06396156 0.02437407]]\n",
      "support vectors = \n",
      "[3.634009 1.730537] -1.0\n",
      "[4.658191 3.507396] -1.0\n",
      "[ 3.223038 -0.552392] -1.0\n",
      "[ 3.457096 -0.082216] -1.0\n",
      "[ 3.023938 -0.057392] -1.0\n",
      "[ 6.960661 -0.245353] 1.0\n",
      "[ 5.286862 -2.358286] 1.0\n",
      "[6.080573 0.418886] 1.0\n",
      "[6.543888 0.433164] 1.0\n",
      "[ 2.912122 -0.202359] -1.0\n"
     ]
    }
   ],
   "source": [
    "b,alphas = oS.b, oS.alphas\n",
    "w = simple.get_w(alphas, dataArr, labelArr)\n",
    "print (\"w = \", w)\n",
    "print (\"b = \", b)\n",
    "print (\"alphas = \", alphas[alphas>0])\n",
    "print (\"support vectors = \")\n",
    "# 打印支撑向量\n",
    "for i in range(100):\n",
    "    if alphas[i]>1e-3: print( dataArr[i],labelArr[i])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "\n",
    "w =  [ 0.62172526 -0.2926272 ]  \n",
    "b =  -2.8697555652712596  \n",
    "alphas =  [[0.13853542 0.0019828  0.00530804 0.05671226 0.00327745 0.04086031\n",
    "  0.04639355 0.07897462 0.06396156 0.02437407]]  \n",
    "\n",
    "support vectors =   \n",
    "[3.634009 1.730537] -1.0  \n",
    "[4.658191 3.507396] -1.0  \n",
    "[ 3.223038 -0.552392] -1.0  \n",
    "[ 3.457096 -0.082216] -1.0  \n",
    "[ 3.023938 -0.057392] -1.0  \n",
    "[ 6.960661 -0.245353] 1.0  \n",
    "[ 5.286862 -2.358286] 1.0  \n",
    "[6.080573 0.418886] 1.0  \n",
    "[6.543888 0.433164] 1.0  \n",
    "[ 2.912122 -0.202359] -1.0  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "utils.showSMO(dataArr,labelArr, alphas, w, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RBF kernel\n",
    "\n",
    "gaussian kernel:  \n",
    "$$\n",
    "k(x, y) = \\exp (\\frac {-||x-y||^2}{2\\sigma^2})\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "sigma=1.3\n",
    "dataArr, labelArr = utils.loadDataSet('testSetRBF.txt')\n",
    "platt = PlattSMO(200, 0.0001, 100, kernel = kernel.gaussianKernel, sigma=sigma)\n",
    "oS = platt.train(dataArr, labelArr)\n",
    "platt.collectCoeff(oS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import numpy as np\n",
    "# b, alphas = oS.b, oS.alphas.T.A[0]\n",
    "# svInd = alphas > 1e-3\n",
    "# datMat = np.array(dataArr);\n",
    "# labelMat = np.array(labelArr).transpose()\n",
    "# supportVectors = datMat[alphas > 1e-3]\n",
    "# labelSV = labelMat[svInd]\n",
    "# utils.testWithFile('testSetRBF.txt', supportVectors, labelSV, alphas, svInd, b,sigma=1.3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy =  1.0\n"
     ]
    }
   ],
   "source": [
    "test_X, test_y = utils.loadDataSet('testSetRBF.txt')\n",
    "predict_y = platt.classify(test_X)\n",
    "accuracy = utils.calculateAccuray(predict_y, test_y)\n",
    "print(\"accuracy = \", accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "\n",
    "accuracy =  1.0  \n",
    "\n",
    "开启verbose可见到以下打印\n",
    "there are 12 Support Vectors  \n",
    "w =  [-4.03558965 -2.68195953]  \n",
    "b =  -10.97366054782148  \n",
    "alphas =  [[2.74385992e+00 2.22044605e-16 1.11022302e-15 2.44375793e+01  \n",
    "  1.14741724e+01 5.77315973e-15 2.42722453e+00 3.33066907e-16  \n",
    "  4.75813884e+01 4.46799894e+01 1.18641142e+02 8.88178420e-16  \n",
    "  7.20968395e+01 6.99070950e+00 1.99521964e+01 2.45163542e+01  \n",
    "  6.87872454e+01 4.44089210e-16]]   \n",
    "support vectors =    \n",
    "[-0.557789  0.375797] -1.0  \n",
    "[-0.475167 -0.346247] -1.0  \n",
    "[ 0.394164 -0.058217] 1.0  \n",
    "[-0.403483  0.474466] -1.0  \n",
    "[-0.012998  0.525985] -1.0  \n",
    "[0.153738 0.491531] -1.0  \n",
    "[0.068286 0.392741] 1.0  \n",
    "[ 0.3843  -0.17657] 1.0  \n",
    "[-0.307768  0.503038] -1.0  \n",
    "[-0.448939  0.176725] 1.0  \n",
    "[0.334204 0.381237] -1.0  \n",
    "[ 0.541359 -0.205969] -1.0  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy =  0.94\n"
     ]
    }
   ],
   "source": [
    "test_X, test_y = utils.loadDataSet('testSetRBF2.txt')\n",
    "predict_y = platt.classify(test_X)\n",
    "accuracy = utils.calculateAccuray(predict_y, test_y)\n",
    "print(\"accuracy = \", accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "accuracy = 0.94"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 手写数字识别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "sigma = 10\n",
    "dataArr,labelArr = utils.loadImages('trainingDigits')\n",
    "platt = PlattSMO(200, 0.0001, 10, kernel = kernel.gaussianKernel, sigma=sigma)\n",
    "oS = platt.train(dataArr, labelArr)\n",
    "platt.collectCoeff(oS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy =  1.0\n"
     ]
    }
   ],
   "source": [
    "test_X, test_y = utils.loadImages('trainingDigits')\n",
    "predict_y = platt.classify(test_X)\n",
    "accuracy = utils.calculateAccuray(predict_y, test_y)\n",
    "print(\"accuracy = \", accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "accuracy =  1.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy =  0.9946236559139785\n"
     ]
    }
   ],
   "source": [
    "test_X, test_y = utils.loadImages('testDigits')\n",
    "predict_y = platt.classify(test_X)\n",
    "accuracy = utils.calculateAccuray(predict_y, test_y)\n",
    "print(\"accuracy = \", accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Expect Result:  \n",
    "accuracy =  0.9946236559139785"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
